from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework.request import exceptions
from rest_framework.authentication import BasicAuthentication

# 判断用户权限的模块
from ..utils.permission import MyPermission,MyPermission1

# 控制版本
from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning

from ..models import  UserInfo,UserToken




def MD5(user):
    import hashlib
    import time

    ctime = str(time.time())

    m = hashlib.md5(bytes(user,encoding='utf-8'))
    m.update(bytes(ctime,'utf-8'))
    return m.hexdigest()




# 定义个用户认证的类;多个模块可以调用
class Authtication(object):

    # 定义一个函数
    def authenticate(self,request):
        # 获取token
        token = request._request.GET.get("token")
        # 从数据库中查看，如果为空则返回数据
        token_obj = UserToken.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed("用户认证失败")

        # 如果认证成功，在rest framework内部会将整个两个字段赋值给request，以供后续操作使用
        return (token_obj.user,token_obj)

    def authenticate_header(self,request):
        pass



# 定义一个访问频率阈值类
from rest_framework.throttling import BaseThrottle
import time


# 记录用户的访问时间，可以存放到数据库，如果定义字典形式存储，放入缓存中
VISIT_LIMIT = {}
class VisitThrottle(object):
    def __init__(self):
        self.history = None
    """60s内只能访问3次"""
    def allow_request(self,request,view):
        """
        最简单的使用
        :param request:
        :param view:
        :return:
        """
        # return True         # 如果是True表示还可以继续访问，没有到达访问频率的要求
        # # return False          # return False表示访问频率太高，被限制

        # 1、获取用户的IP
        remote_addr = request.META.get('REMOTE_ADDR')
        ctime = time.time()
        # 当IP不存在这个字典中，则加入字典；也可以保存到数据库中；key：访问的IP   value：访问的时间
        if remote_addr not in VISIT_LIMIT:
            VISIT_LIMIT[remote_addr] = [ctime,]
            return True
        # 如果存在则从字典中获取访问的记录，并进行判断
        history = VISIT_LIMIT.get(remote_addr)
        # 把用户的记录赋值
        self.history = history
        # 循环用户的访问记录并且获取最后一个值进行判断，是否小于 当前时间 - 10
        # - 10 代表10秒内访问的次数
        while history and history[-1] < ctime - 10:
            """
            这段循环的意思：
            [10:13:50，10:13:40，10:13:30，10:13:20]；获取出来的时间 离现在最远的时间放在最后的
            一直while循环读取这个列表最后一个值，如果时间小于 当前时间 - 10
            则删除这个列表最后一个值
            直到列表最后一个值 大于 当前时间 - 10
            """
            # 删除末尾的值
            history.pop()

        # 控制一定时间内 访问的次数
        if len(history) < 3:
            """
            经过判断时间，删除了一个个数的元素，统计剩下列表元素个数是否小于3
            """
            # 如果元素小于则可以访问，插入一次的访问记录
            history.insert(0,ctime)
            return True

    def wait(self):
        """
        还需要等待多少秒才能访问

        :return:
        """
        # 提示多少能访问
        # 获取当前时间
        ctime = time.time()
        # 10s   - （ 当前时间 - 用户访问的最近一次时间 ）  = 还有几秒可以访问
        return 10 - (ctime - self.history[-1])

class  AuthView(APIView):
    """ 用于用户登录"""
    # 不需要用户登录
    authentication_classes = []
    # 不判断用户的权限
    permission_classes = []
    # 显示访问频率的
    throttle_classes = [VisitThrottle,]

    def post(self,request,*args,**kwargs):
        # 1.在request中获取IP
        # 2.访问记录
        ret = {'code':200,'msg':None}
        try:
            user = request._request.POST.get("username")
            pwd = request._request.POST.get("password")

            obj = UserInfo.objects.filter(username=user,password=pwd).first()
            # 如果从数据库没有查找到用户
            if not obj:
                ret['code'] = 400
                ret['msg'] = "用户民或密码错误"

            # 为用户创建一个token
            token = MD5(user)

            # 存在就更新，不存在就创建
            UserToken.objects.update_or_create(user=obj,defaults={'token':token})
            ret['token'] = token

        except Exception as e:
            # 报错的定义状态码并返回；请求的用户不存在
            ret['code'] = 1002
            ret['msg'] = "请求异常"

        return JsonResponse(ret)




## 模拟订单
order_dict={
    1:{'name':"媳妇",'age':18,'gender':"女",'content':"...."},
    2:{'name':"老狗",'age':18,'gender':"男",'content':"，，，"}
}

order_dict1={
    1:{'name':"媳妇666",'age':18,'gender':"女",'content':"...."},
    2:{'name':"老狗666",'age':18,'gender':"男",'content':"，，，"}
}
class OrderView(APIView):
    """
    订单相关业务
    """
    # 前面变量是标准写法
    # authentication_classes = [Authtication,]
    permission_classes = [MyPermission]


    def get(self,request,*args,**kwargs):

        ret = {'code': 200, 'msg': None, 'data': None}

        # # 判断用户是否登录 如果没有登录则返回提示
        # token = request._request.GET.get("token")
        # if not token:
        #     ret['msg'] = "用户未登录"
        #     return JsonResponse(ret)
        # 定义这个：authentication_classes = [Authtication,] 实现的功能与注释的代码功能一直，判断用户是否登录，这里写成类的方式   可以重复调用
        try:
           ret['data'] = order_dict
        except Exception as e:
            pass
        return JsonResponse(ret)



class UserInfoView(APIView):
    """
    订单相关业务（普通用户和vip 查看）
    """
    # 用户控制版本


    permission_classes = [MyPermission1]
    def get(self,request,*args,**kwargs):

        ret = {'code': 200, 'msg': None, 'data': None}

        # # 判断用户是否登录 如果没有登录则返回提示
        # token = request._request.GET.get("token")
        # if not token:
        #     ret['msg'] = "用户未登录"
        #     return JsonResponse(ret)
        # 定义这个：authentication_classes = [Authtication,] 实现的功能与注释的代码功能一直，判断用户是否登录，这里写成类的方式   可以重复调用
        try:
           ret['data'] = order_dict1
        except Exception as e:
            pass
        return JsonResponse(ret)





class UserView(APIView):
    versioning_class = URLPathVersioning
    def get(self,request,*args,**kwargs):
        print(request.version)
        return HttpResponse("用户列表")




from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination


class PagerView(APIView):
    def get(self,request,*args,**kwargs):
        roles = Roles.objects.all()
        ser = Pa

        pg = PageNumberPagination()
        pg.paginate_queryset(queryset=roles,request=request)